package com.example.springbootdemo.util;

import cn.hutool.core.date.DatePattern;
import com.example.springbootdemo.vo.FileVO;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * minio工具类
 * </p>
 *
 * @author yurenwei
 * @since 2023/9/22
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class MinioUtil {

    private final MinioClient minioClient;


    /**
     * 创建存储桶
     * 如果没有存储桶则创建
     *
     * @param bucketName 存储桶
     */
    @SneakyThrows(Exception.class)
    private void createBucket(String bucketName) {
        if (!bucketExists(bucketName)) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 判断存储桶是否存在
     *
     * @param bucketName 存储桶
     * @return boolean
     */
    @SneakyThrows(Exception.class)
    public boolean bucketExists(String bucketName) {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    /**
     * 获得所有存储桶列表
     *
     * @return List<Bucket>
     */
    @SneakyThrows(Exception.class)
    public List<Bucket> getAllBuckets() {
        return minioClient.listBuckets();
    }

    /**
     * 根据存储桶获取其相关信息
     *
     * @param bucketName 存储桶
     * @return Bucket
     */
    @SneakyThrows(Exception.class)
    public Bucket getBucket(String bucketName) {
        return getAllBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst().orElse(null);
    }

    /**
     * 根据bucketName删除存储桶
     *
     * @param bucketName 存储桶
     */
    @SneakyThrows(Exception.class)
    public void removeBucket(String bucketName) {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * 上传文件
     *
     * @param fileList 文件集合
     * @param bucketName 存储桶
     * @return List<FileVO>
     */
    public List<FileVO> uploadFile(MultipartFile[] fileList, String bucketName) {
        try {
            List<FileVO> list = new ArrayList<>();
            createBucket(bucketName);

            for (MultipartFile file : fileList) {
                String oldName = file.getOriginalFilename();
                assert oldName != null;
                String fileName = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN))+oldName.substring(oldName.lastIndexOf("."));

                minioClient.putObject(PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .stream(file.getInputStream(), file.getSize(), 0)
                        .contentType(file.getContentType())
                        .build()
                );

                String url = this.getObjUrl(bucketName, fileName);
                list.add(new FileVO().setOldFileName(oldName)
                                .setNewFileName(fileName)
                                .setFileUrl(url.substring(0, url.indexOf("?")))
                );
            }
            return list;
        } catch (Exception e) {
            log.error("上传文件出错:{}", e.getMessage());
            return null;
        }
    }


    /**
     * 获取文件链接
     *
     * @param bucketName 存储桶
     * @param fileName 文件名称
     * @return String
     */
    @SneakyThrows(Exception.class)
    public String getObjUrl(String bucketName, String fileName) {
        return minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .method(Method.GET)
                        .expiry(30, TimeUnit.SECONDS)
                        .build()
        );
    }

    /**
     * 下载文件
     *
     * @param bucketName 存储桶
     * @param fileName 文件名称
     */
    @SneakyThrows(Exception.class)
    public InputStream  download(String bucketName, String fileName) {
        return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
    }


    /**
     * 删除文件
     *
     * @param bucketName 存储桶
     * @param fileName 文件名称
     */
    @SneakyThrows(Exception.class)
    public void removeFile(String bucketName, String fileName) {
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
    }

}
